/*
 * MonitorModule.cpp
 *
 *  Created on: 2009-8-6
 *      Author: Administrator
 */
#include "stdafx.h"
#include "MonitorModule.h"

#define ATMDEBUG

int RunAllModule()
{
#ifdef ATMDEBUG
	RunModule(ATM_MOD);
#endif

	return 0;
}

int RunModule(int modID)
{
	string filepath = "";
	string bin = "";

	switch (modID)
	{
	case MON_MOD:
		break;
	case ATM_MOD:
		filepath = ATM_PATH;
		bin = ATM_BIN;
		break;
	default:
		break;
	}

	if (filepath=="" || bin=="")
	{
		return -1;
	}

	pid_t result = fork();
	if (result == 0)
	{
		if (execl(filepath.c_str(), bin.c_str(), NULL) < 0)
		{
			//cout<<"run mod "<<bin<<" error";
			perror("execl");
			exit(0);
		}
	}
	else if (result > 0)
	{        
		monitor[modID-1].pid = result;
        //printf("pid=%d\n", monitor[modID-1].pid);
	}

	return 0;
}


int CallBack_UDP(int nFd, int event, void* param)
{
	int rt = 0;
	switch (event)
	{
	case JSREADEVENT:
		rt = ReadMsg_UDP(nFd);
		break;
	case JSWRITEEVENT:
		//rt = WriteMsg(nFd);
		break;
	case JSEXCEPTIONEVENT:
		break;
	default:
		break;
	}

	return rt;
}

int ReadMsg_UDP(int nFd)
{
	CJSMsg msg;
	int rlen = RecvMsgFrom(nFd, msg, NULL);
	if (rlen < 0) //==0呢？
	{
		return rlen;
	}

	DWORD T = msg.Type();

	int flag = 0;
	int modID = 0;
	int subModID = 0;
	int messageID = 0;

	GetType(T, &flag, &modID, &subModID, &messageID);
	switch (messageID)
	{
	case MSG_HELLO:
		HelloMsgHandle(modID, msg);
		break;
	default:
		break;
	}

	return 0;
}


int HelloMsgHandle(int modID, CJSMsg &msg)
{
	msg.UnPackBegin();
	long time = msg.GetByteArray()->GetLong();
	//cout<<"monitor recv:"<<ctime(&time)<<"modID="<<modID<<endl;
	monitor[modID-1].r = *((time_t*)&time);

	return 0;
}

int SendHelloToAllModule()
{
#ifdef ATMDEBUG
	SendHello(g_nUdpFd, ATM_MOD);
#endif
    
    return 0;
}

//发送的条件：10秒之后，bHasSend == false;
int SendHello(int nFd, int modID)
{
    int length = 0;
	int port = 0;
	switch (modID)
	{
	case MON_MOD:
		port = MON_UDPPORT;
		break;
	case ATM_MOD:
		port = ATM_UDPPORT;
		break;
	default:
		break;
	}

    struct sockaddr_in servAddr;
    servAddr.sin_family       = AF_INET;
    servAddr.sin_port        = htons(port);
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    bzero(&(servAddr.sin_zero), 8);


	//send hello to all module
	if (abs(time(NULL) - monitor[modID-1].s) >= 10 && !monitor[modID-1].bHasSend)
	{
		monitor[modID-1].s = time(NULL);
		//cout<<"monitor send:"<<ctime(&monitor[modID-1].s)<<endl;
		//cout<<"port="<<port<<endl;

	    DWORD T = CreateType(MSG_FLAG_APPLY, MON_MOD, 0, MSG_HELLO);
		CJSMsg msg(T,12);
		msg.GetByteArray()->PutLong(monitor[modID-1].s);
		msg.End();

		length = SendMsgTo(nFd, msg, &servAddr);
		//printf("length=%d\n", length);

		//发送成功失败都得重置标志
		monitor[modID-1].bHasSend = true;
	}

	return length;
}

int MonitorAllModule()
{
#ifdef ATMDEBUG
	ModuleMonitor(ATM_MOD);
#endif
	return 0;
}

//modID N---monitor[N-1]
int ModuleMonitor(int modID)
{
	if (monitor[modID-1].bHasSend)
	{
		//在向send模块发送hello之后的3秒内是否收到数据
		//如果没有收到，则计数，并再次发送hello
		//如果收到，判断是否异常。最后收到时间清0，bmtosendHasSend = false
		if (time(NULL) - monitor[modID-1].s < 4)
		{
			//说明收到数据了
			if (monitor[modID-1].r != 0)
			{
				//cout<<"MONITOR recv time:"<<ctime(&monitor[modID-1].r)<<endl;
				//cout<<"MONITOR send time:"<<ctime(&monitor[modID-1].s)<<endl;
				if (abs(monitor[modID-1].r - monitor[modID-1].s) > 3)
				{
					printf("has recv.but>2  count=%d, modID=%d\n", monitor[modID-1].nCount, modID);
					monitor[modID-1].nCount++;
				}
				monitor[modID-1].r = 0;
				monitor[modID-1].bHasSend = false;
			}
		}
		else
		{
			monitor[modID-1].nCount++;
			monitor[modID-1].bHasSend = false;
			printf("has not recv. count=%d, modID=%d\n", monitor[modID-1].nCount, modID);
		}
	}

	if (monitor[modID-1].nCount >= 3)
	{
		printf("run moduel, modID=%d\n", modID);
		monitor[modID-1].s = time(NULL);

        //kill monitor[modID-1].pid
        char cmd[128];
        memset(cmd, 0, 128);
        sprintf(cmd, "kill -9 %d", monitor[modID-1].pid);
        system(cmd);
		
		RunModule(modID);
		monitor[modID-1].nCount = 0;
	}

	return 0;
}

void* MonitorThread(void*)
{
	while (1)
	{
		SendHelloToAllModule();

		MonitorAllModule();

		//不能睡眠得太久，不能超过1秒
		Sleep(100*1000);
	}
}

void InitMonitorInfo()
{
	for (int i=0; i<MODNUM; i++)
	{
		monitor[i].s = time(NULL);
		monitor[i].r = 0;
		monitor[i].nCount = 0;
		monitor[i].bHasSend = false;
		monitor[i].pid = 0;
	}
}



int main()
{
	signal(SIGCLD, SIG_IGN);
    InitMonitorInfo();
	RunAllModule();
	

	g_nUdpFd = JS_UDPServer(MON_UDPPORT);
	if (g_nUdpFd == -1)
	{
		printf("Monitor UDP Server===============ERROR\n");
		exit(1);
	}
	g_IOModule.AddNewFd(g_nUdpFd, JSRD, &CallBack_UDP);

	pthread_t monThd;
	pthread_create(&monThd, NULL, MonitorThread, NULL);

	while(1)
	{
		sleep(10);
		//printf("main thread ok!!!\n");
	}
	return 0;
}





